package com.vhall.component.plugin.common.utils.algorithm;

import cn.hutool.crypto.digest.MD5;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.vhall.component.framework.common.utils.StringUtils;

import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * PaaS回调MD5方式签名验证
 *
 * @author yuanzh
 * @date 2021/12/14
 */
public class PaasCallbackMd5SignValidator {

    private PaasCallbackMd5SignValidator() {
        throw new IllegalStateException("Utility class");
    }

    /**
     * 生成签名
     *
     * @param params    回调参数，参数务必去除签名
     * @param secretKey 密钥
     * @return 签名
     */
    public static String sign(Map<String, Object> params, String secretKey) {
        String connectors = "|" + MD5.create().digestHex(secretKey, StandardCharsets.UTF_8.toString()) + "|";
        return MD5.create().digestHex(getSignContent(params, connectors));
    }

    /**
     * 校验签名
     *
     * @param params    回调参数，参数务必去除签名
     * @param secretKey 密钥
     * @param signature 原签名
     * @return true=校验通过 false=校验失败
     */
    public static boolean verify(Map<String, Object> params, String secretKey, String signature) {
        String generateSign = sign(params, secretKey);
        return generateSign.equalsIgnoreCase(signature);
    }

    /**
     * 生成签名数据
     *
     * @param params     参数，参数务必去除签名
     * @param connectors 连接符，默认空
     * @return 签名数据
     */
    private static String getSignContent(Map<String, Object> params, String connectors) {
        if (Objects.isNull(connectors)) {
            connectors = "";
        }
        StringBuilder content = new StringBuilder();
        List<String> keys = new ArrayList<>(params.keySet());
        Collections.sort(keys);
        for (String key : keys) {
            Object value = params.get(key);
            if (StringUtils.isNotEmpty(key)) {
                content.append(key).append(connectors);
            }
            if (value instanceof String[] || value instanceof JSONArray || value instanceof JSONObject) {
                value = "Array";
            }
            if (StringUtils.isNotEmpty(String.valueOf(value)) && !"null".equalsIgnoreCase(String.valueOf(value))) {
                content.append(value);
            }
        }
        return content.toString();
    }
}
